/////////////////////////////////////////////////////////////////////
//
// This module is the main entry point, to startup a backup
// process for lotus domino
// Its build, so you could use it in the server, too
// i. e. LNServerAddin
#include "global.h"
#include "lncppapi.h"
#include "Logging.h"
#include "Configurator.h"
#include "BackupDatabase.h"
LNNotesSession  session;

// This function backups the defined database
void backupDatabase(LNDatabase database) {
	DEBUG("backupDatabase() - started!");
	Configurator *config = Configurator::GetInstance();
	try {
		if (IS_DEBUG()) {
			LNString msg;
			msg = "Backup: Processing the database ";
			msg.Append( database.GetFilepath() );
			DEBUG(msg);
		}

		DEBUG("backupDatabase() -Open the Database");
		database.Open();

		DEBUG("backupDatabase() -Defining the BackupDatabase Class");

		BackupDatabase newBackup(database);		

		// TODO Generate dynamical name
		char destpath[4096];
		strcpy(destpath,config->GetBackupdirectory());
		strcat(destpath,DIRECTORY_SEPERATOR);
		strcat(destpath,database.GetFilepath());

		newBackup.MakeBackup(destpath);

		newBackup.CleanUp();

		DEBUG("backupDatabase() -Close the Database");
		database.Close();

		
	} catch (LNSTATUS lnerror)
    {
		ERROR("Unhandled Exception thrown! ",lnerror);
    }

	DEBUG("backupDatabase() - ended!");
}


// This procedure makes the full backup of the whole datadirectory
// this are the .nsf and the .ntf files!
void fullbackup() {
	DEBUG("fullbackup() - started!");

	Configurator *config = Configurator::GetInstance();

	try {
		// Run throu the whole directory and subdirectories
		DEBUG("Calling GetDatabases");
		LNDatabaseArray databaseArray;

		LNGETDBFLAGS flags;
		
		if (config->wantTemplates()) {
			DEBUG("We want also template backup!");
			flags = LNGETDBFLAGS_DATABASES | // We want the databases
				    LNGETDBFLAGS_TEMPLATES | // the templates
					LNGETDBFLAGS_RECURSE;    // for sure all subdirectories
		} else {
			DEBUG("We didn't want a template backup!");
			flags = LNGETDBFLAGS_DATABASES | LNGETDBFLAGS_RECURSE;
		}
		

		session.GetDatabases(&databaseArray, 
			"", // we need the databases local!
			"", // we want it from root
			flags);  

		LNINT count=databaseArray.GetCount();

		if (count<1) {
			INFO("Backup: No Database was found! Exiting");
			return;
		}


		// Iterate throu the databases
		for(LNINT i=0;i<count;i++)
			backupDatabase(databaseArray[i]);


	} catch (LNSTATUS lnerror)
    {
		ERROR("Unhandled Exception thrown! ",lnerror);
    }


	DEBUG("fullbackup() - ended!");
}


void process_full() {
	DEBUG("process_full() - started!");
	Configurator *config = Configurator::GetInstance();
	
	if (config->IsBackup()) {
		fullbackup();
	} else {
		ERROR("FULLDATABASE RECOVERY IS NOT IMPLEMENTED!");
	}

	DEBUG("process_full() - ended!");
}

void process() 
{
	DEBUG("process() - started!");
	Configurator *config = Configurator::GetInstance();

	if (config->IsFull()) {
		DEBUG("Full-Processing is choosen!");
		process_full();
	} else if (config->IsIncremental()) {
		//TODO Please define this
		ERROR("INCREMENTAL DATABASE-PROCESSING IS NOT IMPLEMENTED!");
	} else if (config->IsSingle()) {
		//TODO Please define this
		ERROR("SINGLE DATABASE-PROCESSING IS NOT IMPLEMENTED!");
	} else {
		//TODO Please define this
		ERROR("THIS KIND DATABASE-PROCESSING IS NOT IMPLEMENTED!");
	}

	DEBUG("process() - ended!");
}


int main(int argc, char *argv[])
{
	int returncode;

	Logging *log = Logging::GetInstance();

	// Throw all errors encountered during execution.
	LNSetThrowAllErrors(TRUE);

	try
	{
		session.Init(argc, argv);
		// Create a server add-in task with default status line.
		log->initialise(session,"Backup");

		Configurator *config = Configurator::GetInstance();

		// Read the configuration of the notes.ini
		if (config->ReadConfiguration(&session)) {
			if (config->ParseCommandLine(argc,argv)) {
				if (config->IsValid()) 
					process();
				else
					config->usage();

			} else {
				config->usage();
			}

		} else {
			ERROR("Read of notes.ini failed!");
		}

		config->RemoveInstance();

	} catch (LNSTATUS lnerror)
    {
		ERROR("Unhandled Exception thrown! ",lnerror);
		returncode=8;
    }

    catch (const char *pErrorMessage)
    {
		ERROR(pErrorMessage);
		returncode=8;

    }

    catch (...)
    {
		ERROR("Unhandled Exception thrown! ");
		returncode=8;
    }

	log->RemoveInstance();

	// Terminate the API
	session.Term();

	return returncode;
} // end of main